﻿using HisPro.RedisHelp;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
               // RedisHelper redis = new RedisHelper(2);
               // redis.CustomKey = "Redistest_";

                ////StackExchange(redis);

                // Test_SetValue(redis);
                //Test_GetValue_Tasks(redis);
                CallWithTimeout(FiveSecondMethod, 4000);
                System.Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                System.Console.ReadKey();
            }
        }


        static void Test_SetValue(RedisHelper redis)
        {
            #region Hash

            redis.HashSet("user", "u1", "123");
            redis.HashSet("user", "u2", "1234");
            redis.HashSet("user", "u3", "1235");
            var news = redis.HashGet<string>("user", "u2");

            #endregion Hash

            List<Person> people = new List<Person>()
            {
                new Person(1, "Joe", new List<Contact>()
                {
                    new Contact("1", "123456789"),
                    new Contact("2", "234567890")
                }),
                new Person(2, "Joe2", new List<Contact>()
                {
                    new Contact("12", "1234567289"),
                    new Contact("22", "2345672890")
                })
            };
            ////批量写
            //var batch = redis.GetDatabase().CreateBatch();
            //var Tasks = new List<Task>();
            //for (int i = 0; i < 10000; i++)
            //{
            //    Tasks.Add(batch.ListRightPushAsync("Peoplelist", redis.ConvertJson(people)));
            //}
            //batch.Execute();
            //Task.WaitAll(Tasks.ToArray());
           var ret = redis.HashSet("user", "People", people);
            redis.StringSet("People", people);

            var keys = redis.HashKeys<string>("user");
        }
        static void Test_GetValue_Tasks(RedisHelper redis)
        {
            const int noOfClients = 10000;
            var tasks = new Task[noOfClients];
            var c = 0;
            var ie = 0;
            var watch1 = new Stopwatch();
            //开始计时
            watch1.Start();
            for (var i = 0; i < noOfClients; i++)
            {
                Thread.Sleep(10);
                tasks[i] = Task.Factory.StartNew((object clientNo) =>
                {
                    try
                    {
                        var db = redis.GetDatabase();
                        RedisValue token = Environment.MachineName;
                        // if (db.LockTake("lock_test", token, TimeSpan.FromSeconds(10)))
                        using (new RedisLock(db, "lock_test", TimeSpan.FromSeconds(20)))
                        {
                            //try
                            //{
                            //TODO:开始做你需要的事情
                            //Thread.Sleep(5000);
                            var watch = new Stopwatch();
                            //开始计时
                            watch.Start();
                            if (!redis.KeyExists("atomic-counter")) redis.StringSet("atomic-counter", 0);
                            var counter = redis.StringGet<int>("atomic-counter");
                            var contacts = redis.StringGet<List<Person>>("People");
                            var pl = redis.HashGet<List<Person>>("user", "People");
                            var contactslist = redis.HashGetAll<List<Person>>("Peoplelist");
                            //Thread.Sleep(10);
                            redis.StringSet("atomic-counter", counter + 1);
                            watch.Stop();
                            Console.WriteLine("client {0} released lock,contactslist.Count={1},watch.ElapsedMilliseconds={2},atomic-counter={3}", (int)clientNo, contactslist.Count, watch.ElapsedMilliseconds, counter);
                            //}
                            //finally
                            //{
                            //    db.LockRelease("lock_test", token);
                            //}
                        }
                    }
                    catch (Exception e)
                    {
                        ie++;
                        Console.WriteLine("client {0} " + e.Message, (int)clientNo);
                    }
                    c++;
                    if (noOfClients <= c)
                    {
                        watch1.Stop();
                        Console.WriteLine("client c={0},ie={1},ElapsedMilliseconds={2} ", c, ie, watch1.ElapsedMilliseconds);
                    }
                }, i + 1);
            }
        }

        static void StackExchange(RedisHelper redis)
        {
            DateTime time0 = DateTime.Now;
            DateTime time1 = DateTime.Now;

            #region  StackExchange.Redis
            {
                time0 = DateTime.Now;
                for (int i = 0; i < 100000; i++)
                {
                    redis.StringSet("AAAA", "AAAAAAA");
                }
                time1 = DateTime.Now;
                Console.WriteLine("StackExchange.Redis 赋值 10,0000 次, 耗时: {0} 秒", (time1 - time0).TotalSeconds);



                string valueStr = "";
                time0 = DateTime.Now;
                for (int i = 0; i < 100000; i++)
                {
                    RedisValue value = redis.StringGet("AAAA");
                    valueStr = value;
                }
                time1 = DateTime.Now;
                Console.WriteLine("StackExchange.Redis 取值 10,0000 次, 耗时: {0} 秒", (time1 - time0).TotalSeconds);
                Console.WriteLine(valueStr);
                Console.WriteLine("----------------------------------");
            }

            #endregion

            //#region  ServiceStack.Redis


            //using (RedisClient redisClient = new RedisClient("127.0.0.1", 6379))
            //{
            //    time0 = DateTime.Now;
            //    for (int i = 0; i < 100000; i++)
            //    {
            //        redisClient.Set("AAAA", "AAAAAAA");
            //    }
            //    time1 = DateTime.Now;
            //    Console.WriteLine("ServiceStack.Redis 赋值 10,0000 次, 耗时: {0} 秒", (time1 - time0).TotalSeconds);



            //    string valueStr = "";
            //    time0 = DateTime.Now;
            //    for (int i = 0; i < 100000; i++)
            //    {
            //        valueStr = redisClient.Get<string>("AAAA");
            //    }
            //    time1 = DateTime.Now;
            //    Console.WriteLine("ServiceStack.Redis 取值 10,0000 次, 耗时: {0} 秒", (time1 - time0).TotalSeconds);
            //    Console.WriteLine(valueStr);
            //    Console.WriteLine("----------------------------------");
            //}

            //#endregion

        }

        public static void FiveSecondMethod()
        {
            System.Threading.Thread.Sleep(5000);
            Console.WriteLine("FiveSecondMethod");
        }
        public static void CallWithTimeout(Action action, int timeoutMilliseconds)
        {
            if (action == null) return;
            System.Threading.Thread threadToKill = null;
            Action wrappedAction = () =>
            {
                threadToKill = System.Threading.Thread.CurrentThread;
                action.Invoke();
            };
            var result = wrappedAction.BeginInvoke(null, null);
            if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds))
            {
                wrappedAction.EndInvoke(result);
            }
            else
            {
                threadToKill.Abort();
                throw new Exception("请求超时");
            }
        }
    }

    public class Contact
    {
        public string Type { get; set; }

        public string Value { get; set; }

        public Contact(string type, string value)
        {
            this.Type = type;
            this.Value = value;
        }

    }

    public class Person
    {
        public long Id { get; set; }

        public int Age { get; set; }
        public string Name { get; set; }

        public List<Contact> Contacts { get; set; }

        public Person(long id, string name, List<Contact> contacts)
        {
            this.Id = id;
            this.Name = name;
            this.Contacts = contacts;
        }
    }
}
